package com.duansky;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.regex.Matcher;






import net.sf.json.JSONArray;


public class DataPreProcess {
	
	/**
	 * add by 柯川
	  * @Title: analysisData
	  * @Description: 分析数据
	  * @param @param basePath    输入的原始数据和输出的数据保存的文件夹路径
	  * @param k
	  * @param step
	 */
	public static void analysisData(String basePath, int k, int step){
		DataPreProcess dp=new DataPreProcess(basePath);
		dp.write_complete_data();
		dp.write_stastics(step);
		dp.write_top_k_data(k);
		dp.write_bottom_k_data(k);
		dp.write_random_k_data(k);
		dp.write_hierarchy_k_data(k);
		dp.write_cluster_k_data(new Random().nextInt(),k);
	}
	
	public static void main(String args[]){
		
		String defalut_base_path="/home/cocoa/桌面/data";
		
		DataPreProcess dp=new DataPreProcess(defalut_base_path);
		int k=200;
		int step=50;
		dp.write_complete_data();
		dp.write_stastics(step);
		//dp.write_top_k_data(k);
		//dp.write_bottom_k_data(k);
	//	dp.write_random_k_data(k);
	//	dp.write_hierarchy_k_data(k);
	//	dp.write_cluster_k_data(new Random().nextInt(),k);
	}
	
	//base_path
	String base_path;
	public String getBase_path() {
		return base_path;
	}

	public void setBase_path(String base_path) {
		this.base_path = base_path;
	}
	
	String out_put_path;

	public String getOut_put_path() {
		return out_put_path;
	}

	public void setOut_put_path(String out_put_path) {
		this.out_put_path = out_put_path;
	}
	
	String complete_data;

	public String getComplete_data() {
		return complete_data;
	}

	public void setComplete_data(String complete_data) {
		this.complete_data = complete_data;
	}
	
	//统计数据
	String stastics_data;

	public String getStastics_data() {
		return stastics_data;
	}

	public void setStastics_data(String stastics_data) {
		this.stastics_data = stastics_data;
	}

	//原始txt数据位置
	private String original_data;
	
	public String getOriginal_data() {
		return original_data;
	}

	public void setOriginal_data(String original_data) {
		this.original_data = original_data;
	}
	
	

	//转换后的节点表
	List<Node> node_list; 
	//转换后的边表
	List<Link> link_list;
	//判断是否已经将原始数据读入内存
	boolean is_already_read=false;
	

	
	/**
	 * 
	 * @param original_data_file_name: 输入数据的文件名(注意不是完整路径，只需要输入文件名即可,默认值为"original_data.txt")
	 * @param base_path: 输入的原始数据和输出的数据保存的文件夹路径
	 * @param out_put_file_name:输出数据的文件名(注意不是完整路径，只需要文件名即可,默认值为"data.json")
	 */
	public DataPreProcess(String original_data_file_name,String base_path,String out_put_file_name){
		
		this.base_path=base_path;
		//原始txt数据位置
		if(original_data_file_name.isEmpty() || original_data_file_name.length()==0)
			original_data=base_path+File.separator+"original_data.txt";
		else
			original_data=base_path+File.separator+original_data_file_name;
		
		
		if(out_put_file_name.isEmpty() || out_put_file_name.length()==0)
			this.out_put_path=base_path+File.separator+"data.json";
		else
			this.out_put_path=base_path+File.separator+out_put_file_name;
		
		this.complete_data=base_path+File.separator+"complete_data.json";
		this.stastics_data=base_path+File.separator+"stastics_data.json";
		
		read_data(original_data);
	}
	
	public DataPreProcess(String base_path){
		this("",base_path,"");
	}
	
	public DataPreProcess(){
		
	}
	
	
	//定义7个比较类
	
	class SortByTotalDegreeDesc implements Comparator<Node>{
		public int compare(Node node1,Node node2){
			if(node1.getDtotal()<node2.getDtotal())
				return 1;
			else if(node1.getDtotal()==node2.getDtotal())
				return 0;
			else
				return -1;
			
		}
	}
	class SortByTotalDegreeAsc implements Comparator<Node>{
		public int compare(Node node1,Node node2){
			if(node1.getDtotal()<node2.getDtotal())
				return -1;
			else if(node1.getDtotal()==node2.getDtotal())
				return 0;
			else
				return 1;
			
		}
	}
	class SortByInDegreeDesc implements Comparator<Node>{
		public int compare(Node node1,Node node2){
			if(node1.getDin()<node2.getDin())
				return 1;
			else if(node1.getDin()==node2.getDin())
				return 0;
			else
				return -1;
			
		}
	}
	class SortByInDegreeAsc implements Comparator<Node>{
		public int compare(Node node1,Node node2){
			if(node1.getDin()<node2.getDin())
				return -1;
			else if(node1.getDin()==node2.getDin())
				return 0;
			else
				return 1;
			
		}
	}
	class SortByOutDegreeDesc implements Comparator<Node>{
		public int compare(Node node1,Node node2){	
			if(node1.getDout()<node2.getDout())
				return 1;
			else if(node1.getDout()==node2.getDout())
				return 0;
			else
				return -1;
			
		}
	}
	class SortByOutDegreeAsc implements Comparator<Node>{
			public int compare(Node node1,Node node2){	
				if(node1.getDout()<node2.getDout())
					return -1;
				else if(node1.getDout()==node2.getDout())
					return 0;
				else
					return 1;
				
			}
		}
	class SortByIDASC implements Comparator<Node>{
		@Override
		public int compare(Node o1, Node o2) {
			return o1.getId().compareTo(o2.getId());
		}
		
	}
	

	//将txt转换成json
	public void translate_txt_to_json(String txt_path,String json_path){
		original_data=txt_path;
		out_put_path=json_path;
//		clear();
		read_data(txt_path);
		write_json_data(out_put_path,node_list,link_list);
	}
	//clear
	public void clear(){
		if(!node_list.isEmpty()){
			node_list.clear();
		}
		if(!link_list.isEmpty()){
			link_list.clear();
		}
	}
	
	//将原始数据读入内存
	private void read_data(String uri){		
		File data_path=new File(uri);
		try{
			if(data_path.exists()){
				String path=data_path.getAbsolutePath();
				FileInputStream f = new FileInputStream(Matcher.quoteReplacement(path)); 
				@SuppressWarnings("resource")
				BufferedReader dr=new BufferedReader(new InputStreamReader(f));
				
				//循环读取数据，并存入到列表中
				String line =  dr.readLine();
				
				node_list=new ArrayList<Node>();
				link_list=new ArrayList<Link>();
				
				int state=0;
				
				if(line!=null){
					//第一行特殊处理
					String[] data;
					String from_id="",to_id="";
					int value=0;
					int link_id=0;
					
					//循环读取后面的行
					while(line!= null){ 
						//读取数据
						data=line.split("\t");
						from_id=data[0];
						to_id=data[1];
						value=Integer.parseInt(data[2]);
						//存入边
						link_list.add(new Link(link_id+"",from_id,to_id,value,state));
						System.out.println("Read Current Node:"+from_id);
						link_id++;
						//判断目前的点是否是上一次读取的点
						line = dr.readLine();
						}
				}
				//找到所有的节点
				Set<String> node_set=new HashSet<String>();
				if(!link_list.isEmpty()){
					for(int i=0;i<link_list.size();i++){
						node_set.add(link_list.get(i).getSource());
						node_set.add(link_list.get(i).getTarget());
					}
				}
				//统计节点的出度,初始化所有节点的入度、出度和total为0
				Map<String,Integer> node_din=new HashMap<String,Integer>();
				Map<String,Integer> node_dout=new HashMap<String,Integer>();
				Map<String,Integer> node_dtotal=new HashMap<String,Integer>();
				if(!node_set.isEmpty()){
					for(String node_id:node_set){
						node_din.put(node_id,0);
						node_dout.put(node_id, 0);
						node_dtotal.put(node_id,0);
					}
				}
				if(!link_list.isEmpty()){
					for(Link link:link_list){
						node_din.put(link.getSource(),node_din.get(link.getSource())+1);
						node_dout.put(link.getTarget(),node_dout.get(link.getTarget())+1);
						node_dtotal.put(link.getSource(),node_dtotal.get(link.getSource())+1);
						node_dtotal.put(link.getTarget(),node_dtotal.get(link.getTarget())+1);
					}
				}
				if(!node_set.isEmpty()){
					String label="";
					double x;
					double y;
					double size;
					
					int din;
					int dout;
					int dtotal;
					int node_num=node_set.size();
					Random random=new Random();
					for(String node_id:node_set){
						
						din=node_din.get(node_id);
						dout=node_dout.get(node_id);
						dtotal=node_dtotal.get(node_id);
						
						label="Node Id:"+node_id+";"+"Node Degree:"+dtotal;
						x=random.nextDouble()*node_num;
						y=random.nextDouble()*node_num;
						size=Math.log(dtotal)+2;
						node_list.add(new Node(node_id,label,x,y,size,din,dout,dtotal,state));
					}
				}
			}
			else{
				System.out.println("数据不存在");
			}
		}
		catch (Exception e) {   
		    System.out.println("新建目录操作出错");   
		    e.printStackTrace();
		}
	}
	
	//将数据写入文件
	private void write_data(String uri,String s){		
	  try{
	 
		   File complete_data_file=new File(uri);
		 
	      //if file doesnt exists, then create it
	      if(!complete_data_file.exists()){
	    	  complete_data_file.createNewFile();
	      }
	      else{
	    	  complete_data_file.delete();
	    	  complete_data_file.createNewFile();
	      }
		 
	     //true = append file
	     FileWriter fileWritter = new FileWriter(complete_data_file.getAbsolutePath(),true);
         BufferedWriter bufferWritter = new BufferedWriter(fileWritter);
         bufferWritter.write(s);
         bufferWritter.close();

         System.out.println("Write Done");
 
     }catch(IOException e){
      e.printStackTrace();
     }
	}
	
	//将原始数据转换成json后写入文件
	private void write_json_data(String uri,List<Node> node_list,List<Link> link_list){
		
		change_id(node_list,link_list);
		String data="";
		JSONArray json_array_node_list=JSONArray.fromObject(node_list);
		JSONArray json_array_link_list=JSONArray.fromObject(link_list);
		
		data+="{\"nodes\":";
		data+=json_array_node_list.toString();
		data+=",\"edges\":";
		data+=json_array_link_list.toString();
		data+="}";
		
		write_data(uri,data);
	}
	
	private void change_id(List<Node> node_list,List<Link> link_list){
		
		Map<String,String> map=new HashMap<String,String>();
		int value=0;
		if(!node_list.isEmpty()){
			
			for(Node node:node_list){
				map.put(node.getId(), value+"");
				value++;
			}
			
			for(Node node:node_list){
				node.setId(map.get(node.getId()));
			}
			
			for(Link link:link_list){
				link.setSource(map.get(link.getSource()));
				link.setTarget(map.get(link.getTarget()));
			}
		}
	}
	
	
	//写入原始文件
	void write_complete_data(){
		write_json_data(complete_data,node_list,link_list);
	}
	
	//统计
	void write_stastics(int foot){
		Collections.sort(node_list,new SortByTotalDegreeAsc());
		int last_max_degree=node_list.get(0).getDtotal()<foot?foot:node_list.get(0).getDtotal();
		int number=0;
		
		List<DegreeDistribution> degree_distribution_list=new ArrayList<DegreeDistribution>();
		
		//统计度的分布
		for(Node node:node_list){
			int new_degree=node.getDtotal();
			if(new_degree<=last_max_degree)
				number++;
				else{
					degree_distribution_list.add(new DegreeDistribution(last_max_degree,number));
					int space=(new_degree-last_max_degree)/foot;
					for(int i=1;i<=space;i++){
						last_max_degree+=foot;
						degree_distribution_list.add(new DegreeDistribution(last_max_degree,0));
					}
					number=1;
					last_max_degree+=foot;
				}
		}
		degree_distribution_list.add(new DegreeDistribution(last_max_degree,number));
		
		Stastics stastics=new Stastics();
		stastics.setDegree_distribution(degree_distribution_list);
		
		//统计value值正负的分布
		int positive=0;
		int negative=0;
		int zero=0;
		int current_value=0;
		
		for(Link link:link_list){
			current_value=link.getValue();
			if(current_value>0)
				positive++;
			else if(current_value<0)
				negative++;
			else
				zero++;
		}
		
		FriendEnemyDistribution fed=new FriendEnemyDistribution(positive,negative,zero);
		stastics.setFriend_enemy_distribution(fed);
		
		String data="";
		
		JSONArray json_array_stastics=JSONArray.fromObject(stastics);
		
		data+=json_array_stastics.toString();
		
		write_data(stastics_data,data);
		
	}
		
	//选取节点度数最高的K个节点
	void write_top_k_data(int k){
				
		Set<String> node_set=new HashSet<String>();
		int node_num=node_list.isEmpty()?0:node_list.size();
		k=Math.min(k, node_num);
		for(int i=0;i<k;i++){
			node_set.add(node_list.get(node_num-1-i).getId());
		}
		
		List<Node> new_node_list=new ArrayList<Node>();
		for(Node node:node_list){	
			if(node_set.contains(node.getId())){
				try {
					Node temp_node = (Node) node.clone();
					new_node_list.add(temp_node);
				} catch (CloneNotSupportedException e) {
					e.printStackTrace();
				}
				
			}
		}
		
		List<Link> new_link_list=new ArrayList<Link>();
		for(Link link : link_list){
			if(node_set.contains(link.getSource()) && node_set.contains(link.getTarget())){
				try {
					Link temp_link=(Link) link.clone();
					new_link_list.add(temp_link);
				} catch (CloneNotSupportedException e) {
					e.printStackTrace();
				}	
			}
				
		}
		
		String top_k_data_path=base_path+File.separator+"top_k_data.json";
		write_json_data(top_k_data_path, new_node_list, new_link_list);
		
	}
	
	//选取节点度数最低的K个节点
	void write_bottom_k_data(int k){
				
		Set<String> node_set=new HashSet<String>();
		int node_num=node_list.isEmpty()?0:node_list.size();
		k=Math.min(k, node_num);
		for(int i=0;i<k;i++){
			node_set.add(node_list.get(i).getId());
		}
		
		List<Node> new_node_list=new ArrayList<Node>();
		for(Node node:node_list){
			if(node_set.contains(node.getId())){
				try {
					Node temp_node = (Node) node.clone();
					new_node_list.add(temp_node);
				} catch (CloneNotSupportedException e) {
					e.printStackTrace();
				}
			}
		}
		
		List<Link> new_link_list=new ArrayList<Link>();
		for(Link link : link_list){
			if(node_set.contains(link.getSource()) && node_set.contains(link.getTarget())){
				try {
					Link temp_link=(Link) link.clone();
					new_link_list.add(temp_link);
				} catch (CloneNotSupportedException e) {
					e.printStackTrace();
				}	
			}
		}
		String bottom_k_data_path=base_path+File.separator+"bottom_k_data.json";
		write_json_data(bottom_k_data_path, new_node_list, new_link_list);
	}
		
	//选取节点度数最低的K个节点
	void write_random_k_data(int k){
		int node_num=!node_list.isEmpty()?node_list.size():0;
		Random random=new Random();
		Set<String> node_set=new HashSet<String>();
		k=Math.min(k, node_num);
		while(node_set.size()<=k){
			node_set.add(node_list.get(random.nextInt(node_num)).getId());
		}
		List<Node> new_node_list=new ArrayList<Node>();
		for(Node node:node_list){
			if(node_set.contains(node.getId())){
				try {
					Node temp_node = (Node) node.clone();
					new_node_list.add(temp_node);
				} catch (CloneNotSupportedException e) {
					e.printStackTrace();
				}
			}
		}
		
		List<Link> new_link_list=new ArrayList<Link>();
		for(Link link : link_list){
			if(node_set.contains(link.getSource()) && node_set.contains(link.getTarget())){
				try {
					Link temp_link=(Link) link.clone();
					new_link_list.add(temp_link);
				} catch (CloneNotSupportedException e) {
					e.printStackTrace();
				}	
			}
		}
		String random_k_data_path=base_path+File.separator+"random_k_data.json";
		write_json_data(random_k_data_path, new_node_list, new_link_list);
	}
	
	//节点层级抽样
	void write_hierarchy_k_data(int k){
		
		int node_num=!node_list.isEmpty()?node_list.size():0;
		k=Math.min(k, node_num);
		int foot=node_num/k;
		int start=0;
		Set<String> node_set=new HashSet<String>();
		while(start<node_num){
			node_set.add(node_list.get(start).getId());
			start+=foot;
		}
		List<Node> new_node_list=new ArrayList<Node>();
		for(Node node:node_list){
			if(node_set.contains(node.getId())){
				try {
					Node temp_node = (Node) node.clone();
					new_node_list.add(temp_node);
				} catch (CloneNotSupportedException e) {
					e.printStackTrace();
				}
			}
		}
		
		List<Link> new_link_list=new ArrayList<Link>();
		for(Link link : link_list){
			if(node_set.contains(link.getSource()) && node_set.contains(link.getTarget())){
				try {
					Link temp_link=(Link) link.clone();
					new_link_list.add(temp_link);
				} catch (CloneNotSupportedException e) {
					e.printStackTrace();
				}	
			}
		}
		
		String hierarchy_k_data_path=base_path+File.separator+"hierarchy_k_data.json";
		write_json_data(hierarchy_k_data_path, new_node_list, new_link_list);
	}

	//聚类抽样
	void write_cluster_k_data(int start,int k){
		int node_num=!node_list.isEmpty()?node_list.size():0;
		Random random=new Random();
		int seed=start>=0 && start<node_num ? start : node_num/2;
		k=Math.min(k, node_num);
		int current_num=0;
		Set<String> node_set=new HashSet<String>();
		node_set.add(node_list.get(seed).getId());
		String from_id="";
		String to_id="";
		while(current_num<=k){
			for(Link link : link_list){
				
				from_id=link.getSource();
				to_id=link.getTarget();
				
				if(current_num>k)
					break;
				if(node_set.contains(from_id) || node_set.contains(to_id)){
					node_set.add(from_id);
					node_set.add(to_id);
				}
				current_num=node_set.size();
			}
			if(current_num<=k){
				seed=random.nextInt(node_num);
				node_set.add(node_list.get(seed).getId());
			}
			
		}
		List<Node> new_node_list=new ArrayList<Node>();
		for(Node node:node_list){
			if(node_set.contains(node.getId())){
				try {
					Node temp_node = (Node) node.clone();
					new_node_list.add(temp_node);
				} catch (CloneNotSupportedException e) {
					e.printStackTrace();
				}
			}
		}
		
		List<Link> new_link_list=new ArrayList<Link>();
		for(Link link : link_list){
			if(node_set.contains(link.getSource()) && node_set.contains(link.getTarget())){
				try {
					Link temp_link=(Link) link.clone();
					new_link_list.add(temp_link);
				} catch (CloneNotSupportedException e) {
					e.printStackTrace();
				}	
			}
		}
		
		String cluster_k_data_path=base_path+File.separator+"cluster_k_data.json";
		write_json_data(cluster_k_data_path, new_node_list, new_link_list);
	}
	
	
}
